﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using PersonaLibrary.Data;
using PersonaLibrary.Validation;

namespace PersonaLibrary.ViewModel.ConnectionViewModel
{
    public class EditConnectionViewModel : LinqEditableItem<ConnectionJobEmplDep, View.JobEmploeeRelationView.OrganizationDepartmentEmployeeView>
    {
        #region Private members

        private ValidationItem<Organization> orgValid = new ValidationItem<Organization>();
        private ValidationItem<Department> depValid = new ValidationItem<Department>();
        private ValidationItem<Employee> empValid = new ValidationItem<Employee>();
        private ValidationItem<Job> jobValid = new ValidationItem<Job>();

        #endregion

        #region Ctor

        public EditConnectionViewModel()
        {
            AllInit();
            EditableItem = new ConnectionJobEmplDep();
        }

        public EditConnectionViewModel(int id)
        {
            AllInit();
            EditableItem = Context.ConnectionJobEmplDeps.Single(x => ((ConnectionJobEmplDep)x).Id == id);
            orgValid.ValidationValue = EditableItem.Department.Organization.Name;
            depValid.ValidationValue = EditableItem.Department.Name;
            empValid.ValidationValue = EditableItem.Employee.ToString();
            jobValid.ValidationValue = EditableItem.Job.Name;
            orgValid.IsValid = true;
            depValid.IsValid = true;
            empValid.IsValid = true;
            jobValid.IsValid = true;
            SetEmplValidExpression();
        }

        #endregion

        #region Private method

        private void SetEmplValidExpression()
        {
            System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(@"\s+");
            string[] result = reg.Replace(empValid.ValidationValue, " ").Split(" ".ToCharArray());
            switch (result.Length)
            {
                case 0:
                    empValid.ValidExpression = x => true;
                    break;
                case 1:
                    empValid.ValidExpression = x => x.Surname.StartsWith(result[0]);
                    break;
                case 2:
                    empValid.ValidExpression = x => x.Surname.StartsWith(result[0]) && x.Name.StartsWith(result[1]);
                    break;
                case 3:
                    empValid.ValidExpression = x => x.Surname.StartsWith(result[0]) && x.Name.StartsWith(result[1]) && x.Patronymic.StartsWith(result[2]);
                    break;
            }
        }

        void EmpValidPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "ValidationValue")
            {
                SetEmplValidExpression();
            }
        }               

        void OrgValidPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsValid")
            {
                if (orgValid.IsValid)
                {
                    if (Context.Organizations.Any(x => x.Name == orgValid.ValidationValue))
                        depValid.Source = Context.Departments.Where(x => x.Organization.Name == orgValid.ValidationValue);
                }
            }
        }

        private void AllInit()
        {
            orgValid.PropertyChanged += OrgValidPropertyChanged;
            empValid.PropertyChanged += EmpValidPropertyChanged;
            InitOrgValid();
            InitJobValid();
            InitEmpValid();
            InitDepValid();
        }

        private void InitOrgValid()
        {
            orgValid.Source = Context.Organizations.OrderBy(x => x.Name);
            orgValid.ValidExpression = x => x.Name.StartsWith(orgValid.ValidationValue);
            orgValid.Selector = x => x.Name;            
        }

        private void InitDepValid()
        {            
            depValid.ValidExpression = x => x.Name.StartsWith(depValid.ValidationValue);
            depValid.Selector = x => x.Name;
        }

        private void InitEmpValid()
        {
			empValid.Source = Context.Employees.OrderBy(x => x.Surname);
            empValid.Selector = x => x.ToString();
            empValid.EntitySelector = x => new ValidEntity { SelectedKey = x.ToString(), SelectedValue = x.Id };
        }

        private void InitJobValid()
        {
			jobValid.Source = Context.Jobs.OrderBy(x => x.Name);
            jobValid.ValidExpression = x => x.Name.StartsWith(jobValid.ValidationValue);
            jobValid.Selector = x => x.Name;
        }

        #endregion

        #region Puplic properties

        public ValidationItem<Organization> OrganizationValid
        {
            get { return orgValid; }
        }

        public ValidationItem<Department> DepartmentValid
        {
            get { return depValid; }
        }

        public ValidationItem<Employee> EmployeeValid
        {
            get { return empValid; }
        }

        public ValidationItem<Job> JobValid
        {
            get { return jobValid; }
        }

        #endregion

        #region Parent override

        public override bool CanCommit()
        {
            if (!orgValid.IsValid) return false;
            if (!depValid.IsValid) return false;
            if (!empValid.IsValid) return false;
            if (!jobValid.IsValid) return false;
            return true;
        }

        public override void Commit()
        {
        	List<Organization> organizations =
        		Context.Organizations.Where(x => x.Name == orgValid.ValidationValue).ToList();
			if (organizations.Count > 1)
			{
				MessageBox.Show(string.Format("Невозможно сохрать изменения так как есть органиации с одинаковым названием '{0}'",
				                              orgValid.ValidationValue));
				return;
			}

			if (organizations[0].Departments.Count(x => x.Name == depValid.ValidationValue) > 1)
			{
				MessageBox.Show(string.Format("Невозможно сохрать изменения так как в организации '{0}' есть несколько отделов с одинаковым названием '{1}'",
											  orgValid.ValidationValue, depValid.ValidationValue));
				return;
			}

			EditableItem.Department = organizations[0].Departments.Single(x => x.Name == depValid.ValidationValue);

            int empployeeId = Convert.ToInt32(empValid.Value.SelectedValue);
            Employee emp = Context.Employees.Single(x => ((Employee)x).Id == empployeeId);
            EditableItem.Employee = emp;

        	List<Job> jobs = Context.Jobs.Where(x => x.Name == jobValid.ValidationValue).ToList();

			if(jobs.Count > 1)
			{
				MessageBox.Show(string.Format("Невозможно сохрать изменения так как есть несколько должностей с одинаковым названием '{0}'",
											  jobValid.ValidationValue));
				return;
			}

            EditableItem.Job = jobs[0];
            
            base.Commit();
        }

        public override void Dispose()
        {
            orgValid.PropertyChanged -= OrgValidPropertyChanged;
            empValid.PropertyChanged -= EmpValidPropertyChanged;
        }

        #endregion
    }
}
